#include "core.h"
#include "common.h"
#include "utils.h"
#include "../compiler/compiler.h"


/**
 * @brief 脚本文件所在的根目录 若脚本文件在当前目录，则无需设置
*/
char *rootDir = NULL; 

#define CORE_MODULE VT_TO_VALUE(VT_NULL)

void build_core(VM *vm)
{
    ObjModule *core_module = new_objModule(vm, NULL);
    // 创建核心模块，录入到vm->all_modules
    map_set(vm, vm->all_modules, CORE_MODULE, OBJ_TO_VALUE(core_module));
    // 创建object类并绑定方法
    vm->object_class = define_class(vm, core_module, "object");

    PRIM_METHOD_BIND(vm->object_class, "!", prim_object_not);
    PRIM_METHOD_BIND(vm->object_class, "==(_)", prim_object_equal);
    PRIM_METHOD_BIND(vm->object_class, "!=(_)", prim_object_not_equal);
    PRIM_METHOD_BIND(vm->object_class, "is(_)", prim_object_is);
    PRIM_METHOD_BIND(vm->object_class, "toString", prim_class_to_string);
    PRIM_METHOD_BIND(vm->object_class, "type", prim_object_type);

    // 定义class_of_class类，它是所有meta类的meta类和基类
    vm->class_of_class = define_class(vm, core_module, "class");

    // object_class是任何类的基类
    bind_super_class(vm, vm->class_of_class, vm->object_class);

    PRIM_METHOD_BIND(vm->class_of_class, "name", prim_class_name);
    PRIM_METHOD_BIND(vm->class_of_class, "supertype", prim_class_super_type);
    PRIM_METHOD_BIND(vm->class_of_class, "toString", prim_class_to_string);

    // object类的元信息类obejctMeta
    Class *object_meta_class = define_class(vm, core_module, "obejctMeta");
    // class_of_class类是所有meta类的meta类和基类
    bind_super_class(vm, object_meta_class, vm->class_of_class);

    PRIM_METHOD_BIND(object_meta_class, "same(_,_)", prim_object_meta_same);

    // 绑定各自的meta类
    vm->object_class->obj_header.class = object_meta_class;
    object_meta_class->obj_header.class = vm->class_of_class;
    vm->class_of_class->obj_header.class = vm->class_of_class; // 元信息类回路，meta类终点

    // 执行核心模块
    execute_module(vm, CORE_MODULE, core_module);
}

/**
 * @brief 读取源代码文件
*/
char* read_file(const char *path)
{
    FILE *file = fopen(path, "r");
    if (file == NULL)
    {
        IO_ERROR("Could't open file \"%s\".", path);
    }

    struct stat file_stat;
    stat(path, &file_stat);
    size_t file_size = file_stat.st_size;
    char *file_content = (char *)malloc(file_size + 1);
    if (file_content == NULL)
    {
        MEM_ERROR("Could't allocate memory for reading file \"%s\".\n", path);
    }

    size_t num_read = fread(file_content, sizeof(char), file_size, file);
    if (num_read < file_size)
    {
        IO_ERROR("Could't read file \"%s\".\n", path);
    }
    file_content[file_size] = '\0';

    fclose(file);
    // printf("%s", file_content);
    return file_content;
}

// 返回值是Value类型，放在args[0]中
#define RET_VALUE(value) \
    do { \
        args[0] = value;\
        return true; \
    } while (0);

// 将obj转换为Value后作为返回值
#define RET_OBJ(obj_ptr) RET_VALUE(OBJ_TO_VALUE(obj_ptr))

#define RET_BOOL(boolean) RET_VALUE(OBJ_TO_VALUE(boolean))
#define RET_NUM(num) RET_VALUE(OBJ_TO_VALUE(num))
#define RET_NULL RET_VALUE(OBJ_TO_VALUE(VT_NULL))
#define RET_TRUE RET_VALUE(OBJ_TO_VALUE(VT_TRUE))
#define RET_FALSE RET_VALUE(OBJ_TO_VALUE(VT_FALSE))

// 设置线程报错
#define SET_ERROR_FALSE(vm_ptr, err_msg) \
    do { \
        vm_ptr->cur_thread->error_obj = OBJ_TO_VALUE(new_objString(vm_ptr, err_msg, strlen(err_msg))); \
        return false; \
    } while (0);

// 绑定方法func到class_ptr的类
#define PRIM_METHOD_BIND(class_ptr, method_name, func) \
{ \
    uint32_t length = strlen(method_name); \
    int global_idx = get_index_from_symbol_table(&vm->all_method_names, method_name, length); \
    if (global_idx == -1) \
    { \
        global_idx = add_symbol(vm, &vm->all_method_names, method_name, length);\
    } \
    Method method; \
    method.type = MT_PRIMITIVE; \
    method.orim_fn = func; \
    bind_method(vm, class_ptr, (uint32_t)global_idx, method); \
}

/**
 * @brief object取反
*/
static bool prim_object_not(VM *vm UNUSED, Value *args)
{
    RET_VALUE(VT_TO_VALUE(VT_FALSE));
}

static bool prim_object_equal(VM *vm UNUSED, Value *args)
{
    Value bool_value = BOOL_TO_VALUE(value_is_equal(args[0], args[1]));
    RET_VALUE(bool_value);
}

static bool prim_object_not_equal(VM *vm UNUSED, Value *args)
{
    Value bool_value = BOOL_TO_VALUE(!value_is_equal(args[0], args[1]));
    RET_VALUE(bool_value);
}

/**
 * @brief 类args[0]是否为类args[1]的子类
*/
static bool prim_object_is(VM *vm, Value *args)
{
    if (!VALUE_IS_CLASS(args[1]))
    {
        RUNTIME_ERROR("argument must be class!");
    }
    
    Class *this_class = get_class_obj(vm, args[0]);
    Class *base_class = (Class *)(args[1].obj_header);

    // 也有可能是多级继承
    while (base_class != NULL)
    {
        if (this_class == base_class)
        {
            RET_VALUE(VT_TO_VALUE(VT_TRUE));
        }
        base_class = base_class->super_class;
    }

    // 找不到
    RET_VALUE(VT_TO_VALUE(VT_FALSE));
}

/**
 * @brief 返回args[0]所属class的名字
*/
static bool prim_object_to_string(VM *vm UNUSED, Value *args)
{
    Class *class = args[0].obj_header->class;
    Value name_value = OBJ_TO_VALUE(class->name);
    RET_VALUE(name_value);
}

/**
 * @brief 返回对象args[0]所属的类
*/
static bool prim_object_type(VM *vm, Value *args)
{
    Class *class = get_class_obj(vm, args[0]);
    RET_OBJ(class);
}

/**
 * @brief 返回类名
*/
static bool prim_class_name(VM *vm UNUSED, Value *args)
{
    RET_OBJ(VALUE_TO_CLASS(args[0]).name);
}

/**
 * @brief 返回args[0]的基类
*/
static bool prim_class_super_type(VM *vm UNUSED, Value *args)
{
    Class *class = VALUE_TO_CLASS(args[0]);
    if (class->super_class != NULL)
    {
        RET_OBJ(class->super_class);
    }
    RET_VALUE(VT_TO_VALUE(VT_NULL));
}

/**
 * @brief 返回类名
*/
static bool prim_class_to_string(VM *vm UNUSED, Value *args)
{
    RET_OBJ(VALUE_TO_CLASS(args[0]).name);
}

/**
 * @brief 返回args[1]和args[2]是否相等
*/
static bool prim_object_meta_same(VM *vm UNUSED, Value *args)
{
    Value bool_value = BOOL_TO_VALUE(value_is_equal(args[1], args[2]));
    RET_VALUE(bool_value);
}

/**
 * @brief 在table中查找符号，找到返回索引
*/
int get_index_from_symbol_table(SymbolTable *table, const char *symbol, uint32_t length)
{
    ASSERT(length != 0, "length of symbol is 0!");
    uint32_t index = 0;
    while (index < table->count)
    {
        if (length == table->datas[index].length && memcmp(table->datas[index].str, symbol, length) == 0)
        {
            return index;
        }
        index ++;
    }
    return -1;
}

/**
 * @brief 在table中添加符号symbol 返回其索引
*/
int add_symbol(VM *vm, SymbolTable *table, const char *symbol, uint32_t length)
{
    ASSERT(length != 0, "length of symbol is 0!");
    String string;
    string.str = ALLOCATE_ARRAY(vm, char, length + 1);
    memcpy(string.str, symbol, length);
    string.str[length] = '\0';
    string.length = length;
    String_buffer_add(vm, table, string);
    return table->count - 1;
}

/**
 * @brief 定义类
*/
static Class* define_class(VM *vm, ObjModule *obj_module, const char *name)
{
    Class *class = new_raw_class(vm, name, 0);  // 创建类

    // 把类作为普通变量在模块中定义
    define_module_var(vm, obj_module, name, strlen(name), OBJ_TO_VALUE(class));
    return class;
}

/**
 * @brief 绑定方法
*/
void bind_method(VM *vm , Class *class, uint32_t index, Method method)
{
    if (index >= class->methods.count)
    {
        Method empty_pad = { MT_NONE, {0} };
        Method_buffer_fill_write(vm, &class->methods, empty_pad, index - class->methods.count + 1);
    }
    class->methods.datas[index] = method;
}

/**
 * @brief 绑定基类
*/
void bind_super_class(VM *vm, Class *sub_class, Class *super_class)
{
    sub_class->super_class = super_class;
    // 继承基类属性数
    sub_class->field_num += super_class->field_num;

    uint32_t idx = 0;
    while (idx < super_class.methods.count)
    {
        bind_method(vm, sub_class, idx, super_class.methods.datas[idx]);
        idx ++;
    }
}

/**
 * @brief 从module中获取名为module_name的模块
*/
static ObjModule* get_module(VM *vm, Value module_name)
{
    Value value = map_get(vm->all_modules, module_name);
    if (value.value_type == VT_UNDEFINED)
    {
        return NULL;
    }

    return VALUE_TO_OBJMODULE(value);
}

/**
 * @brief 载入模块module_name并编译
*/
static ObjThread* load_module(VM *vm, Value module_name, const char *module_code)
{
    ObjModule *module = get_module(vm, module_name);

    if (module == NULL)
    {
        ObjString *mod_name = VALUE_TO_OBJSTR(module_name);
        ASSERT(mod_name->value.start[mod_name->value.length] == '\0', "string.value.start is not terminated!");

        module = new_objModule(vm, mod_name->value.start);
        map_set(vm, vm->all_modules, mod_name, OBJ_TO_VALUE(module));

        // 继承核心模块中的变量
        ObjModule *core_module = get_module(vm, CORE_MODULE);
        uint32_t idx = 0;
        while (idx < core_module->module_var_name.count)
        {
            define_module_var(vm, module, 
            core_module->module_var_name.datas[idx].str, 
            strlen(core_module->module_var_name.datas[idx].str), 
            core_module->module_var_value.datas[idx]);
            idx ++;
        }
    }
    ObjFn *fn = compile_module(vm, module, module_code);
    ObjClosure *obj_closure = new_objClosure(vm, fn);
    ObjThread *module_thread = new_objThread(vm, obj_closure);

    return module_thread;
}
/**
 * @brief 执行模块，目前为空，桩函数
*/
VMResult execute_module(VM *vm, Value module_name, const char *module_core)
{
    return VM_RESULT_ERROR;
}

/**
 * @brief 确保符号已添加到符号表
*/
int ensure_symbol_exist(VM *vm, SymbolTable *table, const char *symbol, uint32_t length)
{
    int symbol_index = get_index_from_symbol_table(table, symbol, length);
    if (symbol_index == -1)
    {
        return add_symbol(vm, table, symbol, length);
    }

    return symbol_index;
}   